"""
文件上传 API 路由定义 (routes/upload_routes.py)

使用 Flask Blueprint 组织文件上传和查询相关的 API 端点。
"""
from flask import Blueprint, jsonify, request, send_from_directory
from services.upload_service import (
    handle_file_upload, get_all_uploads, get_upload, 
    update_upload_tags, get_uploads_by_date, import_files_from_directory,
    get_recent_imports, sync_tags_from_uploads
)
from services.openai_service import get_image_tags
from models.upload import get_upload_dates, get_upload_by_id, load_uploads
from config.config import APP_CONFIG
from models.db_models import Tag
from models import db_session
import logging
import os

# 设置日志记录器
logger = logging.getLogger(__name__)

# 文件上传 API 蓝图
upload_bp = Blueprint('uploads', __name__)

@upload_bp.route('/uploads/<path:filepath>')
def uploaded_file_route(filepath):
    """
    API 端点：提供对已上传文件的访问。
    支持按日期组织的子文件夹。
    
    Args:
        filepath: 文件路径 (e.g., '20240801/image.jpg' or 'legacy_image.png')
    """
    upload_dir = APP_CONFIG['UPLOAD_FOLDER']
    # 安全地构建文件系统路径
    # os.path.normpath 清理路径，os.path.abspath 获取绝对路径
    # 确保请求的路径在 UPLOAD_FOLDER 之下，防止路径遍历
    safe_path = os.path.normpath(os.path.join(upload_dir, filepath))
    if not safe_path.startswith(os.path.abspath(upload_dir)):
        return jsonify({"error": "禁止访问"}), 403

    # send_from_directory 是 Flask 提供的安全发送文件的方法
    return send_from_directory(upload_dir, filepath)

@upload_bp.route('/upload', methods=['POST'])
def upload_files_route():
    """API 端点：处理文件上传。"""
    if 'files' not in request.files:
        return jsonify({"error": "请求中缺少 'files' 部分"}), 400
    
    files = request.files.getlist('files')
    tags = request.form.get('tags', '')
    
    uploaded_files, error = handle_file_upload(files, tags)
    
    if error:
        return jsonify({"error": error}), 400
    
    return jsonify(uploaded_files), 201 # 201 Created

@upload_bp.route('/uploads', methods=['GET'])
def get_uploads_route():
    """API 端点：获取所有上传记录列表。"""
    uploads = get_all_uploads()
    return jsonify(uploads)

@upload_bp.route('/uploads/<file_id>', methods=['GET'])
def get_single_upload_route(file_id):
    """API 端点：根据 ID 获取单个上传记录。"""
    upload, error = get_upload(file_id)
    if error:
        return jsonify({"error": error}), 404
    return jsonify(upload)

@upload_bp.route('/uploads/<file_id>/tags', methods=['PUT'])
def update_tags_route(file_id):
    """API 端点：更新指定上传文件的标签。"""
    if not request.json or 'tags' not in request.json:
        return jsonify({"error": "无效请求，需要包含 'tags' 的 JSON 数据"}), 400
    
    tags = request.json['tags']
    upload, error = update_upload_tags(file_id, tags)
    if error:
        return jsonify({"error": error}), 404
    return jsonify(upload)

@upload_bp.route('/upload-dates', methods=['GET'])
def get_all_upload_dates_route():
    """API 端点：获取所有包含上传记录的日期列表。"""
    dates = get_upload_dates()
    return jsonify(dates)

@upload_bp.route('/uploads/by-date/<date>', methods=['GET'])
def get_date_uploads_route(date):
    """API 端点：获取指定日期的所有上传记录。"""
    uploads, error = get_uploads_by_date(date)
    if error:
        return jsonify({"error": error}), 404
    return jsonify(uploads)

@upload_bp.route('/import-files', methods=['POST'])
def import_files_route():
    """API 端点：从 import 目录导入文件到指定日期目录。"""
    # 获取目标日期 (可选)
    data = request.json or {}
    target_date = data.get('date')
    
    # 获取是否进行 AI 分析
    analyze_images = data.get('analyze_images', False)

    logger.info(f"导入文件请求: 目标日期={target_date}, AI分析={analyze_images}")
    
    # 验证日期格式
    if target_date and (not target_date.isdigit() or len(target_date) != 8):
        return jsonify({"error": "无效的日期格式，请使用 YYYYMMDD"}), 400

    # 调用服务层方法进行导入
    results, error = import_files_from_directory(target_date, analyze_images)
    
    if error:
        logger.warning(f"导入文件失败: {error}")
        return jsonify({"error": error}), 400
    
    # 返回导入结果
    total = results['importedCount'] + results['skippedCount']
    message = f"成功导入 {results['importedCount']} 个文件 (总计 {total})"
    
    # 如果有未支持的文件，添加到消息中
    if results.get('unsupportedFiles', 0) > 0:
        message += f"，跳过 {results['unsupportedFiles']} 个不支持的文件"
    
    # 如果启用了AI分析，计算成功分析的文件数量
    if analyze_images:
        analyzed_count = sum(1 for file in results['importedFiles'] if file.get('tags'))
        message += f"，成功分析 {analyzed_count} 个图片"
        # 添加分析计数到结果
        results['analyzedCount'] = analyzed_count
    
    return jsonify({
        "message": message,
        "results": results
    })

@upload_bp.route('/uploads/<file_id>/analyze', methods=['POST'])
def analyze_upload_image_route(file_id):
    """API 端点：对现有上传图片进行 AI 分析，生成中英文标签。"""
    # 获取上传记录
    upload, error = get_upload(file_id)
    if error:
        return jsonify({"error": error}), 404
    
    # 构建文件完整路径
    path_parts = upload.get('path', '').split('/')
    if len(path_parts) >= 2:
        date_folder = path_parts[0]
        filename = path_parts[1]
        file_path = os.path.join(APP_CONFIG['UPLOAD_FOLDER'], date_folder, filename)
    else:
        filename = upload.get('filename')
        file_path = os.path.join(APP_CONFIG['UPLOAD_FOLDER'], filename)
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        return jsonify({"error": f"文件不存在: {file_path}"}), 404
    
    # 使用配置的AI服务分析图片
    # 获取是否使用Ollama的配置
    from config.config import APP_CONFIG
    use_ollama = APP_CONFIG.get('OLLAMA_API', {}).get('USE_OLLAMA', False)
    model_name = APP_CONFIG.get('OLLAMA_API', {}).get('MODEL', 'deepseek-vision') if use_ollama else APP_CONFIG.get('OPENAI_API', {}).get('MODEL', 'gpt-4o-mini')
    
    logger.info(f"使用{'Ollama的' + model_name if use_ollama else 'OpenAI的' + model_name}分析图片: {file_path}")
    
    # 执行图片分析
    ai_tags = get_image_tags(file_path)
    
    if not ai_tags:
        # 获取更详细的错误信息
        error_msg = "图片分析失败，无法获取标签"
        if use_ollama:
            error_msg += "。可能Ollama服务不可用，请确保Ollama已启动，或在设置中临时切换到OpenAI。"
        return jsonify({"error": error_msg}), 500
    
    if 'cn_tags' not in ai_tags:
        return jsonify({"error": "图片分析结果格式不正确，未包含中文标签"}), 500
    
    # 更新上传记录的标签
    current_tags = upload.get('tags', [])
    # 添加新的 AI 生成标签
    for tag in ai_tags.get('cn_tags', []):
        if tag not in current_tags:
            current_tags.append(tag)
    
    # 保存标签到数据库记录
    updated_upload, update_error = update_upload_tags(file_id, current_tags)
    
    if update_error:
        return jsonify({"error": f"无法更新标签: {update_error}"}), 500
    
    # 添加 AI 标签字段到响应
    updated_upload['ai_tags'] = ai_tags
    
    try:
        # 更新数据库中的AI分析结果
        session = db_session()
        from models.db_models import Upload as UploadDB
        upload_record = session.query(UploadDB).filter(UploadDB.id == file_id).first()
        if upload_record:
            upload_record.ai_analysis = ai_tags
            upload_record.analyzed = True
            session.commit()
        session.close()
    except Exception as e:
        logging.error(f"更新AI分析结果时出错: {e}")
    
    return jsonify({
        "message": f"图片分析成功 (使用{'Ollama的' + model_name if use_ollama else 'OpenAI的' + model_name})",
        "upload": updated_upload,
        "ai_tags": ai_tags
    })

@upload_bp.route('/uploads/recent-imports', methods=['GET'])
def get_recent_imports_route():
    """API 端点：获取最近导入的表情图片。"""
    # 获取限制数量 (可选参数)
    limit = request.args.get('limit', 20, type=int)
    
    # 调用服务函数获取最近导入
    recent_imports = get_recent_imports(limit)
    
    return jsonify(recent_imports)

@upload_bp.route('/tags/stats', methods=['GET'])
def get_tag_stats_route():
    """API 端点：获取标签使用统计数据。"""
    try:
        # 获取限制数量 (可选参数)
        limit = request.args.get('limit', 50, type=int)
        # 最小出现次数 (可选参数)
        min_count = request.args.get('min_count', 1, type=int)
        
        session = db_session()
        # 查询标签统计数据
        tags = session.query(Tag)\
            .filter(Tag.count >= min_count)\
            .order_by(Tag.count.desc())\
            .limit(limit)\
            .all()
            
        # 转换为字典列表
        result = [{
            'id': tag.id,
            'name': tag.name,
            'count': tag.count,
            'created_at': tag.created_at.isoformat() if tag.created_at else None,
            'last_used': tag.last_used.isoformat() if tag.last_used else None
        } for tag in tags]
        
        session.close()
        return jsonify(result)
        
    except Exception as e:
        logging.error(f"获取标签统计数据时出错: {e}")
        return jsonify({"error": f"获取标签统计数据时出错: {str(e)}"}), 500

@upload_bp.route('/tags/sync', methods=['POST'])
def sync_tags_route():
    """API 端点：同步所有上传文件的标签到标签表，重新计算统计数据。"""
    try:
        # 调用服务层方法进行同步
        result, error = sync_tags_from_uploads()
        
        if error:
            return jsonify({"error": error}), 500
        
        # 可选：从结果中移除标签计数详情（可能很长）
        if 'tag_counts' in result:
            # 计算标签总数，但不返回详细列表
            tag_count = len(result['tag_counts'])
            result['tag_count'] = tag_count
            del result['tag_counts']
        
        return jsonify({
            "message": f"标签同步成功：处理了 {result['total_uploads']} 个上传记录，更新了 {result['total_tags']} 个标签",
            "result": result
        })
        
    except Exception as e:
        logging.error(f"同步标签数据时出错: {e}")
        return jsonify({"error": f"同步标签数据时出错: {str(e)}"}), 500 